package cn.yangliu.shiro.config;

import cn.yangliu.comm.tools.StringUtils;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;

import javax.annotation.Resource;
import javax.servlet.Filter;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * 作者 杨柳
 * 创建时间 2017-09-08 00:04
 */
@Configuration
@EnableConfigurationProperties(value = ShiroProperties.class)
@ConditionalOnProperty(prefix = "spring.shiro", value = "enable", matchIfMissing = true)
@AutoConfigureAfter(ShiroConfig.class)
public class ShiroFactoryConfig {
    @Resource
    private ShiroProperties properties;

    @Bean
    @DependsOn("securityManager")
    public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager,FormAuthenticationFilter formAuthenticationFilter) {
        ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean();
        factoryBean.setSecurityManager(securityManager);
        factoryBean.setLoginUrl(properties.getLoginUrl());
        factoryBean.setSuccessUrl(properties.getSuccessUrl());
        Map<String, Filter> filters = new LinkedHashMap<>();
        filters.put("authc", formAuthenticationFilter);
        LinkedHashMap<String, String> filterChainDefinitionMap = getFilterChainDefinitionMap();
        factoryBean.setFilters(filters);
        factoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        return factoryBean;
    }

    @Bean
    public FilterRegistrationBean formAuthenticationFilterRegistrationBean(FormAuthenticationFilter formAuthenticationFilter){
        FilterRegistrationBean bean = new FilterRegistrationBean();
        bean.setFilter(formAuthenticationFilter);
        bean.setEnabled(false);
        return bean;
    }

    @Bean
    public FormAuthenticationFilter formAuthenticationFilter() {
        try {
            Class<? extends FormAuthenticationFilter> clazz = properties.getAuthFormFilterClassName();
            FormAuthenticationFilter filter = clazz.newInstance();
            filter.setUsernameParam(properties.getUsernameParam());
            filter.setPasswordParam(properties.getPasswordParam());
            return filter;
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage(), e);
        }

    }
    private LinkedHashMap<String, String> getFilterChainDefinitionMap() {
        LinkedHashMap<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
        String chain = properties.getFilterChainDefinition().trim();
        String[] k_vs = chain.split(";");
        for (String k_v : k_vs) {
            k_v = k_v.trim();
            if (StringUtils.isEmpty(k_v)) {
                continue;
            }
            String[] array = k_v.split("=");
            String key = array[0].trim();
            String value = array[1].trim();
            if (StringUtils.isEmpty(key) || StringUtils.isEmpty(value)) {
                continue;
            }
            if (filterChainDefinitionMap.containsKey(key)) {
                continue;
            }
            filterChainDefinitionMap.put(key, value);
        }
        return filterChainDefinitionMap;
    }
}
